package com.foreverwin.mes.warehouse.strategy;

import com.foreverwin.mes.common.dto.PrintDto;
import com.foreverwin.mes.common.enums.HandleEnum;
import com.foreverwin.mes.common.model.PrintRequest;
import com.foreverwin.mes.common.service.PrintService;
import com.foreverwin.mes.core.exception.BusinessException;
import com.foreverwin.mes.core.utils.DateUtil;
import com.foreverwin.mes.core.utils.SpringUtil;
import com.foreverwin.mes.core.utils.StringUtils;
import com.foreverwin.mes.meapi.model.Item;
import com.foreverwin.mes.meapi.service.ItemService;
import com.foreverwin.mes.warehouse.constant.Constants;
import com.foreverwin.mes.warehouse.dto.InventoryReceiveDto;
import com.foreverwin.mes.warehouse.model.InventoryReceiveConfirm;
import com.foreverwin.mes.warehouse.service.InventoryReceiveConfirmService;
import com.google.common.base.Strings;
import com.sap.me.extension.Services;
import com.sap.me.inventory.InventoryDataField;
import com.sap.me.inventory.InventoryServiceInterface;
import com.sap.me.inventory.InventoryStatusEnum;
import com.sap.me.inventory.InventoryValidateAndAddRequest;

import java.math.BigDecimal;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 1.接收到此类型的物料时，系统自动进行库存拆分
 * 2.打印相应的库存标贴
 * 3.库存标识：凭证号+项次+流水号
 * 4.MES库存状态置为不可用状态
 *
 * @author Ervin Chen
 * @date 2020/2/10 13:50
 */
public class InventoryReceiveSplitStrategy implements InventoryReceiveStrategy {

    private InventoryServiceInterface inventoryServiceInterface;
    private InventoryReceiveConfirmService inventoryReceiveConfirmService;
    private PrintService printService;
    private ItemService itemService;

    @Override
    public void initService(String site) {
        inventoryServiceInterface = Services.getService("com.sap.me.inventory", "InventoryService", site);
        inventoryReceiveConfirmService = SpringUtil.getBean(InventoryReceiveConfirmService.class);
        printService = SpringUtil.getBean(PrintService.class);
        itemService = SpringUtil.getBean(ItemService.class);
    }

    @Override
    public boolean validate(InventoryReceiveDto inventoryReceiveDto) {
        String documentNo = inventoryReceiveDto.getDocumentNo();
        String documentYear = inventoryReceiveDto.getDocumentYear();
        String documentItem = inventoryReceiveDto.getDocumentItem();
        String site = inventoryReceiveDto.getSite();
        String item = inventoryReceiveDto.getItem();
        String storageLocation = inventoryReceiveDto.getStorageLocation();
        String centralStorageLocation = inventoryReceiveDto.getCentralStorageLocation();
        String vendorId = inventoryReceiveDto.getVendorId();
        String vendor = inventoryReceiveDto.getVendor();
        String vendorLot = inventoryReceiveDto.getVendorLot();
        String batchNumber = inventoryReceiveDto.getBatchNumber();
        String expireDate = inventoryReceiveDto.getExpireDate();
        Double qty = inventoryReceiveDto.getQty();
        Double minPackQty = inventoryReceiveDto.getMinPackQty();

        //校验凭证号是否为空
        if (StringUtils.isBlank(documentNo)) {
            throw BusinessException.build("warehouse.inventoryReceive.documentNoNotBlank", new Object[]{});
        }
        //校验项次是否为空
        if (StringUtils.isBlank(documentItem)) {
            throw BusinessException.build("warehouse.inventoryReceive.documentItemNotBlank", new Object[]{});
        }
        //校验工厂是否为空
        if (StringUtils.isBlank(site)) {
            throw BusinessException.build("warehouse.inventoryReceive.documentItemNotBlank", new Object[]{});
        }
        //校验物料是否为空
        if (StringUtils.isBlank(item)) {
            throw BusinessException.build("warehouse.inventoryReceive.itemNotBlank", new Object[]{});
        }
        //校验线边仓是否为空
        if (StringUtils.isBlank(storageLocation)) {
            throw BusinessException.build("warehouse.inventoryReceive.storageLocationNotBlank", new Object[]{});
        }
        //校验中央存储地点是否为空
        if (StringUtils.isBlank(centralStorageLocation)) {
            throw BusinessException.build("warehouse.inventoryReceive.centralStorageLocationNotBlank", new Object[]{});
        }
        //校验数量是否正确
        if (qty == null || qty <= 0) {
            throw BusinessException.build("warehouse.inventoryReceive.qtyNotBlankOrNotValid", new Object[]{});
        }
        //校验最小包装数量是否正确
        if (minPackQty == null || minPackQty <= 0) {
            throw BusinessException.build("warehouse.inventoryReceive.minPackQtyNotBlankOrNotValid", new Object[]{});
        }

        return true;
    }

    @Override
    public void receive(InventoryReceiveDto inventoryReceiveDto) {
        String sendTime = inventoryReceiveDto.getSendTime();
        String documentNo = inventoryReceiveDto.getDocumentNo();
        String documentYear = inventoryReceiveDto.getDocumentYear();
        String documentItem = inventoryReceiveDto.getDocumentItem();
        String site = inventoryReceiveDto.getSite();
        String item = inventoryReceiveDto.getItem();
        String itemBo = inventoryReceiveDto.getItemBo();
        String unitOfMeasure = inventoryReceiveDto.getUnitOfMeasure();
        String storageLocation = inventoryReceiveDto.getStorageLocation();
        String centralStorageLocation = inventoryReceiveDto.getCentralStorageLocation();
        String vendorId = inventoryReceiveDto.getVendorId();
        String vendor = inventoryReceiveDto.getVendor();
        String vendorLot = inventoryReceiveDto.getVendorLot();
        String batchNumber = inventoryReceiveDto.getBatchNumber();
        String expireDate = inventoryReceiveDto.getExpireDate();
        Double qty = inventoryReceiveDto.getQty();
        Double minPackQty = inventoryReceiveDto.getMinPackQty();

        BigDecimal[] result = BigDecimal.valueOf(qty).divideAndRemainder(BigDecimal.valueOf(minPackQty));
        int batchNum = result[0].intValue();
        if (result[1].compareTo(BigDecimal.ZERO) > 0) {
            batchNum = batchNum + 1;
        }

        for (int i = 1; i <= batchNum; i++) {
            String inventoryId = MessageFormat.format("{0}-{1}-{2}", documentNo, documentItem, Strings.padStart(String.valueOf(i), 3, '0'));
            Double qtyOnHand = i == batchNum && result[1].doubleValue() > 0 ? result[1].doubleValue() : minPackQty;

            List<InventoryDataField> assemblyDataList = new ArrayList<>();
            //物料凭证号
            InventoryDataField documentNoDataField = new InventoryDataField();
            documentNoDataField.setAttribute(Constants.MAT_DOC_NUM);
            documentNoDataField.setValue(documentNo);
            assemblyDataList.add(documentNoDataField);
            //物料凭证年份
            InventoryDataField documentYearDataField = new InventoryDataField();
            documentYearDataField.setAttribute(Constants.MAT_DOC_YEAR);
            documentYearDataField.setValue(documentYear);
            assemblyDataList.add(documentYearDataField);
            //物料凭证行号
            InventoryDataField documentItemDataField = new InventoryDataField();
            documentItemDataField.setAttribute(Constants.LINE_NUM);
            documentItemDataField.setValue(documentItem);
            assemblyDataList.add(documentItemDataField);
            //供应商ID
            InventoryDataField vendorDataField = new InventoryDataField();
            vendorDataField.setAttribute(Constants.VENDOR);
            vendorDataField.setValue(vendorId);
            assemblyDataList.add(vendorDataField);
            //供应商批次
            InventoryDataField vendorLotDataField = new InventoryDataField();
            vendorLotDataField.setAttribute(Constants.VENDOR_LOT);
            vendorLotDataField.setValue(vendorLot);
            assemblyDataList.add(vendorLotDataField);
            //中央存储地点
            InventoryDataField centralStorageLocationDataField = new InventoryDataField();
            centralStorageLocationDataField.setAttribute(Constants.CENTRAL_STORAGE_LOCATION);
            centralStorageLocationDataField.setValue(centralStorageLocation);
            assemblyDataList.add(centralStorageLocationDataField);
            //收货批次
            InventoryDataField batchNumberDataField = new InventoryDataField();
            batchNumberDataField.setAttribute(Constants.BATCH_NUMBER);
            batchNumberDataField.setValue(batchNumber);
            assemblyDataList.add(batchNumberDataField);
            //过期日期
            InventoryDataField expireDateDataField = new InventoryDataField();
            expireDateDataField.setAttribute(Constants.EXPIRE_DATE);
            expireDateDataField.setValue(expireDate);
            assemblyDataList.add(expireDateDataField);
            //物料最小包装数量
            InventoryDataField minPackQtyDataField = new InventoryDataField();
            minPackQtyDataField.setAttribute(Constants.MIN_PACK_QTY);
            minPackQtyDataField.setValue(minPackQty.toString());
            assemblyDataList.add(minPackQtyDataField);

            InventoryValidateAndAddRequest addRequest = new InventoryValidateAndAddRequest();
            addRequest.setInventoryId(inventoryId);
            addRequest.setItemRef(itemBo);
            addRequest.setQuantityOnHand(BigDecimal.valueOf(qtyOnHand));
            addRequest.setStatus(InventoryStatusEnum.HOLD);
            addRequest.setStorageLocationRef(HandleEnum.STORAGE_LOCATION.getHandle(site, storageLocation));
            addRequest.setAssemblyDataList(assemblyDataList);

            try {
                inventoryServiceInterface.validateAndAdd(addRequest);
            } catch (com.sap.me.frame.domain.BusinessException e) {
                throw BusinessException.build(e.getMessage());
            }

            //保存物料接收确认记录
            InventoryReceiveConfirm inventoryReceiveConfirm = new InventoryReceiveConfirm();
            inventoryReceiveConfirm.setHandle(HandleEnum.INVENTORY_RECEIVE_CONFIRM.getHandle(site, inventoryId));
            inventoryReceiveConfirm.setSite(site);
            inventoryReceiveConfirm.setInventoryId(inventoryId);
            inventoryReceiveConfirm.setItemBo(itemBo);
            inventoryReceiveConfirm.setUnitOfMeasure(unitOfMeasure);
            inventoryReceiveConfirm.setDocumentNo(documentNo);
            inventoryReceiveConfirm.setDocumentItem(documentItem);
            inventoryReceiveConfirm.setBatchNumber(batchNumber);
            inventoryReceiveConfirm.setVendor(vendorId);
            inventoryReceiveConfirm.setVendorLot(vendorLot);
            inventoryReceiveConfirm.setQty(qtyOnHand);
            inventoryReceiveConfirm.setIsConfirmed(Constants.NOT_CONFIRMED);
            inventoryReceiveConfirm.setExpireDate(expireDate);
            inventoryReceiveConfirm.setIssueDateTime(DateUtil.parse(sendTime));
            inventoryReceiveConfirm.setCreateUserBo(Services.getUserRef());
            inventoryReceiveConfirm.setCreatedDateTime(DateUtil.parse(sendTime));
            inventoryReceiveConfirmService.insert(inventoryReceiveConfirm);

            //打印标贴
            printLabel(inventoryReceiveDto, inventoryId);
        }
    }

    public void printLabel(InventoryReceiveDto inventoryReceiveDto, String inventoryId) {
        String itemBo = inventoryReceiveDto.getItemBo();
        Item itemDo = itemService.selectItem(itemBo);

        PrintRequest<Map<String,Object>> printRequest = new PrintRequest<>();
        Map<String,Object> printMap = new HashMap<>();
        printMap.put( "ITEM", inventoryReceiveDto.getItem() );
        printMap.put( "UNIT", itemDo.getUnitOfMeasure() );
        printMap.put( "ITEM_DESC", itemDo.getDescription() );
        printMap.put( "EXP_DATE", inventoryReceiveDto.getExpireDate() );
        printMap.put( "QTY", inventoryReceiveDto.getQty() );
        printMap.put( "INV_BATCH", inventoryReceiveDto.getBatchNumber() );
        printMap.put( "INVENTORY_ID", inventoryId );

        printRequest.setPrinter("XPS");
        printRequest.setLabelQty(1);
        printRequest.setTemplate("doc");
        printRequest.addPrintData(printMap);

        PrintDto printDto = new PrintDto();
        printDto.setPrintRequest(printRequest);
        printService.print(printDto);
    }
}
